using System;
using System.Collections.Generic;
using Nvigorate.Xml;

namespace Nvigorate.Relational.Mapping.Interface
{
    /// <summary>
    /// Describes the nature of the relationship from the
    /// perspective of the subject
    /// </summary>
    public enum Relationship
    {
        /// <summary>
        /// Many To One
        /// </summary>
        Child,
        /// <summary>
        /// One to Many
        /// </summary>
        Parent,
        /// <summary>
        /// One to One
        /// </summary>
        Pair,
        /// <summary>
        /// Mainy to Many
        /// </summary>
        Peer,
    }

    /// <summary>
    /// Used to establish a relationship between
    /// types in the domain model
    /// </summary>
    public interface ITargetRelationship : ILinqToXml
    {
        /// <summary>
        /// Detects whether or not the relationship in question 
        /// defines the same relationship just from the
        /// relative's perspective
        /// </summary>
        /// <param name="relationship"></param>
        /// <returns></returns>
        bool IsInverse(ITargetRelationship relationship);

        /// <summary>
        /// Describes the nature of the relationship from the
        /// perspective of the subject
        /// </summary>
        Relationship Relationship { get; set; }

        /// <summary>
        /// The name of the relative
        /// </summary>
        string Relative { get; set; }

        /// <summary>
        /// The name of the relative type
        /// </summary>
        Type RelativeType { get; set; }

        /// <summary>
        /// The name of the property in which the
        /// relative is stored
        /// </summary>
        string RelativeProperty { get; set; }

        /// <summary>
        /// The name of the subject
        /// </summary>
        string Subject { get; set; }

        /// <summary>
        /// The name of the subject type
        /// </summary>
        Type SubjectType { get; set; }
    }

    public interface IRelateOneToMany<T> : ITargetRelationship
    {
        /// <summary>
        /// Defines how the subject and relative relate to one another
        /// </summary>
        Dictionary<T, T> Constraints { get; }
    }

    public interface IRelateManyToMany : ITargetRelationship
    {
        /// <summary>
        /// Defines how the subject and relative are tied together
        /// through an external container (usually a table)
        /// </summary>
        RelationContainer Container { get; set; }
    }
}